#include "./free4.h"
#include "../mem_inner.h"


/* 内存管理-FreeRTOS-heap4 */

#if defined (CONFIG_MEM_TYPE_FREERTOS)

/* static sal func */

static void *_init(void *obj, void *addr_start, void *addr_end)
{
    size_t size;

    if (addr_start >= addr_end)
    {
        return NULL;
    }
    else
    {
        size = (uint32_t)addr_end - (uint32_t)addr_start;
    }

    free4_prvHeapInit(obj, addr_start, size);
    return obj;
}

static void _free(void *obj, void *ptr)
{
    free4_vPortFree((_free4_obj_t *)obj, ptr);
}

static void *_malloc(void *obj, size_t bytes)
{
    void *ptr = NULL;

    ptr = free4_pvPortMalloc((_free4_obj_t *)obj, bytes);
    return ptr;
}

static void *_realloc(void *obj, void *ptr, size_t bytes)
{
    void *pp;
    
    /* Allocate area of requested size. */
    pp = free4_pvPortMalloc((_free4_obj_t *)obj, bytes);

    /* If no memory, keep existing block and indicate failure to reallocate. */
    if (pp == NULL) return pp;

    /* Copy existing block if we were given one. */
    if (ptr)
    {
        /* Make copy of data. */
        memcpy(pp, ptr, bytes);

        /* And we're done with the original block. */
        free4_vPortFree((_free4_obj_t *)obj, ptr);
    }

    /* Return newly allocated block. */
    return pp;

}

static void _get_info(void *obj, uint32_t *total, uint32_t *used, uint32_t *max_used)
{
    uint32_t fre;

    fre = free4_xPortGetFreeHeapSize(obj);
    *total = free4_xPortGetTotalHeapSize(obj);
    *used = *total - fre;
    fre = free4_xPortGetMinimumEverFreeHeapSize(obj);
    *max_used = *total - fre;
}

/* export */


const _mem_sal_opt mem_free4_sal_opt = 
{
    .name = "FreeRTOS-heap4",
    .func_init = _init,
    .func_free = _free,
    .func_malloc = _malloc,
    .func_realloc = _realloc,
    .func_get_info = _get_info,
};

#endif // CONFIG_MEM_TYPE_FREERTOS

